package com.igoal.service;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.userdetails.UserDetails;

import com.igoal.dto.UserDTO;
import com.igoal.entity.Audit;
import com.igoal.utils.BaseSynchronizeAttributeWithOther;
import com.igoal.utils.EntityUtils;
import com.igoal.utils.ObjectHelper;

public abstract class BaseService<M extends BaseSynchronizeAttributeWithOther<T>, T extends Audit, PK extends Serializable> {
	protected Log logger;
	
	@Autowired
	protected ApplicationContextService contextService;
	
	protected <K extends Audit> void setAuditDate(K entity){
		entity.setCreateDate(new Date());
		entity.setUpdateDate(new Date());
	}
	
	@SuppressWarnings("unchecked")
	protected void convertListEntitiesToDTOs(List<T> entities, List<M> dtos, Class<M> clazz){
		for(T entity : entities){
			try {
				M obj = (M) ObjectHelper.instantiateObject(clazz);
				obj.initFrom(entity);
				dtos.add(obj);
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
			
		}
	}
	
	@SuppressWarnings("unchecked")
	protected void convertListDTOsToEntities(List<M> dtos, List<T> entities, Class<M> clazz){
		for(M dto : dtos){
			try {
				T obj = (T) ObjectHelper.instantiateObject(clazz);
				dto.copyAttributesTo(obj);
				entities.add(obj);
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
			
		}
	}
	
	protected boolean isAdministrator(UserDTO user){
		//TODO: implement
		return false;
	}
	
	protected void debug(Object message){
		checkLoggerExist();
		if(logger.isDebugEnabled()){
			logger.debug(message);
		}
	}
	
	protected void debug(Object message, Throwable throwable){
		checkLoggerExist();
		if(logger.isDebugEnabled()){
			logger.debug(message, throwable);
		}
	}
	
	protected void error(Object message){
		checkLoggerExist();
		logger.error(message);
	}
	
	protected void error(Object message, Throwable throwable){
		checkLoggerExist();
		logger.error(message, throwable);
	}
	
	private void checkLoggerExist(){
		if(logger == null){
			logger = LogFactory.getLog(this.getClass());
		}
	}
	
	public String getUserInSession(){
		return SecurityContextHolder.getContext().getAuthentication().getName();
	}
	
	protected boolean isLoginUser(){
		String userInSession = getUserInSession();
		return !userInSession.equalsIgnoreCase("roleAnonymous");
	}
	
	protected boolean isAdmin(UserDetails user){
		if(user == null){
			return false;
		}
		
		GrantedAuthority[] authorities = user.getAuthorities();
		for(GrantedAuthority authority : authorities){
			if(authority.getAuthority().equals("ROLE_ADMIN")){
				return true;
			}
		}
		
		return false;
	}
	
	protected void updateEntity(Audit audit){
//		audit.setUpdateDate(new Date());
		EntityUtils.updateAuditInformation(audit);
	}
}










